WebAssembly Component Model
概要
WASM の相互運用可能性を高めるための仕様
データ表現
関数呼び出し規約
メモリ管理
例外処理
開発体験
内部では、以下の 3 つの仕様を取りまとめている
2024 年 10 月現在 Phase 1(Feature Proposal)ではあるが既に多くのツールが開発されており、広く受け入れられている
e.g.
WASI Preview 2 も、このコンポーネントモデルのインタフェースに従って実現される なぜ Component Model が登場したか
そのため、関数を呼び出す側と呼び出される側の両方が一定のルールに従う必要があった
具体例
以下のような Rust のコードを WASM としてビルドし、JavaScript から呼び出すことを考える
code:rs
struct A {
x: u32,
y: u8,
z: u16,
}
pub fn get_x(value: &A) -> u32 { value.x }
pub fn get_y(value: &A) -> u8 { value.y }
pub fn get_z(value: &A) -> u16 { value.z }
この場合、以下のように呼び出せることを期待するが、これは実行できない
code:js
const a = { x: 1, y: 2, z: 3 };
const x = instance.exports.get_x(a);
解決策
code:rs
const a = { x: 1, y: 2, z: 3 };
// 線形メモリを u8 の配列として JavaScript から操作する
const memory = new UInt8Array(instance.exports.memory.buffer);
// x の値のコピー
// y の値のコピー
// z の値のコピー
// コピーしたオブジェクトの先頭の添字を引数に関数を呼び出す
const x = instance.exports.get_x(0);
問題点
上記では、A オブジェクトは以下のようなルールで表現されていることを前提としている
x、y、z の順で属性値がメモリ上に並んで保存されること
属性値以外のデータはメモリ上に保存されないこと
関数を呼び出す側と呼び出される側の両方がこのルールに従う必要がある
しかし、この ルールが必ず守られるという保証は無い
そのため、コンパイラやビルド時の設定によっては、属性値が異なる順序で並んでいるケースもある
e.g. x、z、y
この場合、以下のように C と同じようにメモリ上に表現するよう指定する必要がある code:rs
struct A {
x: u32,
y: u8,
z: u16,
}
上記のような問題点は、WASM のユースケースが単純であったり、小規模の場合は問題なかった
WASM の作成者と利用者の間でコミュニケーションによって合意を取る WASM ファイルを作成するプログラミング言語やツールが少数であれば、使っているツールに合わせれば良い 上記のような問題点
データ表現以外にも以下のような問題もあった
関数呼び出し規約
メモリ管理
例外処理
開発体験
しかし、 WASM が登場して時間が経つにつれ、WASM が利用されるプロジェクトが巨大・複雑化すると問題が顕在化してきた
WASM が利用されるプロジェクトが巨大・複雑化
複数の WASM ファイルの利用
WASM をビルドターゲットとして指定できるビルドツールも増えてきた Component Model は上記の 5 つの問題すべてを解決するために策定された
参考